/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package drinkcounter.web.servlet;

import com.google.inject.Inject;
import com.google.inject.Singleton;
import drinkcounter.DrinkCounterService;
import drinkcounter.model.Drink;
import drinkcounter.model.Participant;
import drinkcounter.model.Party;
import drinkcounter.util.PathInfoHelper;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;

/**
 *
 * @author Toni
 */
@Singleton
public class PartyAPIServlet extends HttpServlet{

    private static final Logger log = LoggerFactory.getLogger(PartyAPIServlet.class);

    @Inject private DrinkCounterService service;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doRequest(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doRequest(req, resp);
    }

    private void doRequest(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String action = getAction(req);
        log.debug("action: "+action);
        if(StringUtils.isBlank(action)){
            printXml(req, resp);
        }else if("add-drink".equals(action)){
            addDrink(req, resp);
        }else if("add-participant".equals(action)){
            addParticipant(req,resp);
        }else{
            resp.getOutputStream().close();
        }
        
    }

    private String getAction(HttpServletRequest req){
        String pathInfo = req.getPathInfo();
        String[] parameters = PathInfoHelper.splitPathInfo(pathInfo);
        if(parameters.length < 2){
            return "";
        }else{
            return parameters[1];
        }
        
    }
    private String getPartyId(HttpServletRequest req){
        String pathInfo = req.getPathInfo();
        String[] parameters = PathInfoHelper.splitPathInfo(pathInfo);
        return parameters[0];
    }

    private void printXml(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/xml");
        OutputStream out = resp.getOutputStream();
        try {
            String partyId = getPartyId(req);
            Party party = service.getParty(partyId);
            DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
            DocumentBuilder b = f.newDocumentBuilder();
            Document d = b.newDocument();
            
            Node rootNode = d.createElement("party");
            d.appendChild(rootNode);

            Node idNode = d.createElement("id");
            idNode.setTextContent(party.getId());
            rootNode.appendChild(idNode);

            Node partyNameNode = d.createElement("name");
            partyNameNode.setTextContent(party.getName());
            rootNode.appendChild(partyNameNode);

            Node participantsNode = d.createElement("participants");
            rootNode.appendChild(participantsNode);

            for (Participant participant : service.listParticipants(partyId)) {
                participantsNode.appendChild(createParticipantNode(d, participant, partyId));
            }

            StreamResult streamResult = new StreamResult(out);
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer serializer = tf.newTransformer();
            serializer.setOutputProperty(OutputKeys.ENCODING,"UTF-8");
            serializer.setOutputProperty(OutputKeys.INDENT,"yes");
            serializer.transform(new DOMSource(d), streamResult);
            
        } catch (Exception ex) {
            log.error("Error building xml response", ex);
        }finally{
            out.close();
        }
    }

    private Node createParticipantNode(Document document, Participant participant, String partyId) {
        Node participantNode = document.createElement("participant");

        Node idNode = document.createElement("id");
        idNode.setTextContent(participant.getId());
        participantNode.appendChild(idNode);

        Node nameNode = document.createElement("name");
        nameNode.setTextContent(participant.getName());
        participantNode.appendChild(nameNode);

        participantNode.appendChild(createDrinksNode(document, participant));
        
        return participantNode;
    }

    private Node createDrinksNode(Document d, Participant participant){
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Node drinksNode = d.createElement("drinks");
        List<Drink> drinks = service.getDrinks(participant.getId(), null, null);
        Node countNode = d.createElement("count");
        countNode.setTextContent(Integer.toString(drinks.size()));
        drinksNode.appendChild(countNode);
        for (Drink drink : drinks) {
            Node drinkNode = d.createElement("drink");
            Node timeStampNode = d.createElement("timestamp");
            timeStampNode.setTextContent(format.format(drink.getTimeStamp()));
            drinkNode.appendChild(timeStampNode);
            drinksNode.appendChild(drinkNode);
        }
        return drinksNode;
    }

    private void addDrink(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{
        String participantIdentifier = req.getParameter("participant-id");
        service.addDrink(participantIdentifier);
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/plain");
        PrintWriter out = resp.getWriter();
        out.print(service.getDrinks(participantIdentifier, null, null).size());
        out.close();
    }

    private void addParticipant(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String participantName = req.getParameter("name");
        String partyId = getPartyId(req);
        Participant participant = service.addParticipant(participantName, partyId);
        resp.setContentType("text/plain");
        resp.setCharacterEncoding("UTF-8");
        PrintWriter out = resp.getWriter();
        out.print(participant.getId());
        out.close();
    }
}
